package main

import (
	"fmt"
)

/*
	练习四：
	1.结构体：声明、调用
	2.面向对象、抽象
*/

func main() {
	/*
		题一：编写一个程序，要求如下
		1) 声明一个结构体Circle, 字段为 radius
		2) 声明一个方法area和Circle绑定，可以返回面积。
	*/
	var c Circle
	c.radius = 4.2
	res := c.area()
	fmt.Println(res)

	/*
		题二：
		编写结构体(MethodUtils)，编程一个方法，方法不需要参数，在方法中打印一个10*8 的矩形，
		在main方法中调用该方法。
	*/
	var mu MethodUtils
	mu.print()

	/*
		编写一个方法，提供m和n两个参数，方法中打印一个m*n的矩形
	*/
	mu.print2(3, 4)

	/*
		编写一个方法算该矩形的面积(可以接收长len，和宽width)， 将其作为方法返回值。在main方法中调用该方法，接收返回的面积值并打印。
	*/
	area := mu.stArea(3.5, 6)
	fmt.Println(area)
	/*
	 编写方法：判断一个数是奇数还是偶数
	*/
	mu.JudgeNum(33)
	/*
		定义小小计算器结构体(Calcuator)，实现加减乘除四个功能
		实现形式1：分四个方法完成:
		实现形式2：用一个方法搞定
	*/
	var c1 Calcuator
	c1.Num1 = 40.6
	c1.Num2 = 2.7
	fmt.Println(c1.getSum())
	fmt.Println(c1.getSub())
	fmt.Println(c1.getMul())
	fmt.Println(c1.getDiv())

	/*
		学生案例：
		1) 编写一个Student结构体，包含name、gender、age、id、score字段，分别为string、string、int、int、float64类型。
		2) 结构体中声明一个say方法，返回string类型，方法返回信息中包含所有字段值。
		3) 在main方法中，创建Student结构体实例(变量)，并访问say方法，并将调用结果打印输出。
	*/
	var stu = Student{
		name:   "tom",
		gender: "male",
		age:    18,
		id:     54610,
		score:  108,
	}
	stuInfo := stu.Say()
	fmt.Println(stuInfo)

	/*
		小狗案例
		1) 编写一个Dog结构体，包含name、age、weight字段
		2) 结构体中声明一个say方法，返回string类型，方法返回信息中包含所有字段值。
		3) 在main方法中，创建Dog结构体实例(变量)，并访问say方法，将调用结果打印输出。
	*/
	var dog = Dog{
		name:   "dingding",
		age:    2,
		weight: 20,
	}
	fmt.Println(dog.Say())

	/*
		盒子案例
		1) 编程创建一个Box结构体，在其中声明三个字段表示一个立方体的长、宽和高，长宽高要从终端获取
		2) 声明一个方法获取立方体的体积。
		3) 创建一个Box结构体变量，打印给定尺寸的立方体的体积
	*/
	//var box Box
	//fmt.Println("请输入盒子的长...")
	//fmt.Scanf("%v", &box.length)
	//fmt.Println("请输入盒子的宽...")
	//fmt.Scanf("%v", &box.width)
	//fmt.Println("请输入盒子的高...")
	//fmt.Scanf("%v", &box.height)
	//
	//volume := box.getVolume()
	//fmt.Println(volume)

	/*
		景区门票案例
		1) 一个景区根据游人的年龄收取不同价格的门票，比如年龄大于18，收费20元，其它情况门票免费.
		2) 请编写Visitor结构体，根据年龄段决定能够购买的门票价格并输出
	*/
	var v1 = Visitor{
		name: "jerry",
		age:  18,
	}
	v1.showPrice()

	var v2 = Visitor{
		"tom", 11,
	}
	v2.showPrice()

	/*
		抽象
		银行取存钱系统
	*/
	var account = Account{
		AccountNo: "45278000",
		Pwd:       "1234567890.",
		Balance:   500.4,
	}
	account.Despite(3000.0, "1234567890.")
	account.WithDraw(400, "1234567890.")
	account.Query("1234567890.")

}

//题一
type Circle struct {
	radius float64
}

func (c Circle) area() float64 {
	return 3.14 * c.radius * c.radius
}

//题二
type MethodUtils struct{}

func (mu MethodUtils) print() {
	for i := 0; i < 10; i++ {
		for j := 0; j < 8; j++ {
			fmt.Print("*")
		}
		fmt.Println()
	}

}

func (mu MethodUtils) print2(m, n int) {
	for i := 0; i < m; i++ {
		for j := 0; j < n; j++ {
			fmt.Print("*")
		}
		fmt.Println()
	}

}

func (mu MethodUtils) stArea(width, length float64) float64 {
	return width * length
}

func (mu MethodUtils) JudgeNum(num int) {
	if num%2 == 0 {
		fmt.Println("偶数。。。")
	} else {
		fmt.Println("奇数。。。")
	}
}

type Calcuator struct {
	Num1, Num2 float64
}

//和
func (c Calcuator) getSum() float64 {
	return c.Num1 + c.Num2
}

//差
func (c Calcuator) getSub() float64 {
	return c.Num1 - c.Num2
}

func (c Calcuator) getMul() float64 {
	return c.Num1 * c.Num2
}

func (c Calcuator) getDiv() float64 {
	return c.Num1 / c.Num2
}

//面向对象:学生案例
type Student struct {
	name   string
	gender string
	age    int
	id     int
	score  float64
}

func (s Student) Say() string {
	stuInfo := fmt.Sprintf("student的信息name：%v，gender：%v，age：%v，id：%v，score：%v",
		s.name, s.gender, s.age, s.id, s.score)
	return stuInfo
}

//面向对象：小狗案例
type Dog struct {
	name   string
	age    int
	weight int
}

func (d Dog) Say() string {
	dogInfo := fmt.Sprintf("dog的信息name：%s，age：%d，weight：%d", d.name, d.age, d.weight)
	return dogInfo
}

//面向对象：盒子案例
type Box struct {
	height, width, length float64
}

func (b *Box) getVolume() float64 {
	return b.height * b.width * b.length
}

//面向对象:景区门票案例
type Visitor struct {
	name string
	age  int
}

func (v *Visitor) showPrice() {
	if v.age >= 18 {
		fmt.Printf("游客%v，年龄%v，门票20元\n", v.name, v.age)
	} else {
		fmt.Printf("游客%v，年龄%v，门票免费\n", v.name, v.age)
	}
}

//面向对象-抽象
type Account struct {
	AccountNo string
	Pwd       string
	Balance   float64
}

//存款
func (account *Account) Despite(money float64, pwd string) {
	if pwd != account.Pwd {
		fmt.Println("密码错误！")
		return
	}

	if money <= 0 {
		fmt.Println("输入的钱数不正确！")
		return
	}
	account.Balance += money
	fmt.Println("存钱成功！")
}

//取钱
func (account *Account) WithDraw(money float64, pwd string) {
	if pwd != account.Pwd {
		fmt.Println("密码错误！")
		return
	}
	if money <= 0 {
		fmt.Println("输入的钱数不正确！")
		return
	}
	account.Balance -= money
	fmt.Println("取钱成功！")
}

//查询
func (account *Account) Query(pwd string) {
	if pwd != account.Pwd {
		fmt.Println("密码错误！")
		return
	}
	fmt.Printf("您的账号：%v，余额为%v\n", account.AccountNo, account.Balance)
}
